#include <iostream>
#include <cstdio>
#include <memory>
#include <vector>
#include <string>
#include "HttpServer.hpp"
#include "Err.hpp"
#include "Log.hpp"
#include "Utility.hpp"

// 当用户用浏览器访问'/'根目录时，我们不能把整个文件夹里面的内容都给他，存在一个主页面页面
// 假设访问根目录的子目录，也要给他一个子目录的主页面
static const std::string webroot = "./wwwroot";
static const std::string defaulthHomePage = "index.html";
static const std::string page_404 = "./wwwroot/404.html";

const std::string SEP = "\r\n";

class HttpRequst
{
public:
    HttpRequst() : path_(webroot)
    {
    }
    ~HttpRequst() {}
    void Print()
    {
        logMessage(Debug, "method_:%s url_:%s httpversion_:%s", method_.c_str(), url_.c_str(), httpversion_.c_str());
        logMessage(Debug, "path_:%s", path_.c_str());
        logMessage(Debug, "suffix_:%s", suffix_.c_str());
    }

public:
    std::string method_;
    std::string url_;
    std::string httpversion_;
    std::vector<std::string> headerbody_;
    std::string path_;
    std::string suffix_;
};
HttpRequst Deserialize(std::string &requst)
{
    HttpRequst hr;
    std::string line = Utility::ReadLine(requst, SEP);
    Utility::ReadOneLine(line, &hr.method_, &hr.url_, &hr.httpversion_);
    hr.path_ += hr.url_;
    if (hr.path_[hr.path_.size() - 1] == '/')
        hr.path_ += defaulthHomePage;

    auto pos = hr.path_.rfind('.'); // 获取后缀：C++、html和Css语言需要根据后缀进行解析
    if (pos != std::string::npos)
    {
        hr.suffix_ = hr.path_.substr(pos);
    }
    while (!requst.empty())
    {
        size_t pos = requst.find(SEP);
        hr.headerbody_.push_back(requst.substr(0, pos));
        requst.erase(0, pos + SEP.size());
    }
    return hr;
}
std::string GetSuffix(const std::string &suffix)
{
    std::string context;
    if (suffix == ".html" || suffix == ".htm")
        context += "text/html";
    else if (suffix == ".css")
        context += "text/css";
    else if (suffix == ".js")
        context += "application/x-javascript";
    else if (suffix == ".png")
        context += "image/png";
    else if (suffix == ".jpg")
        context += "image/jpeg";
    else if (suffix == ".ico")
        context += "application/x-ico";
    else
    {
    }
    return context + SEP;
}
std::string HandlResponse(std::string &requst)
{
    // 对请求进行处理
    std::cout << "-----------------------" << std::endl;
    std::cout << requst << std::endl;
    // std::string body = "<html><body><h1>This is title</h1><p>This is paragraph</p></body></html>";
    // std::string body = "<html><body style=""background-color:yellow""><h2 style=""background-color:red"">This is a heading</h2><p style=""background-color:green"">This is a paragraph.</p></body></html>";
     
    // 2. 反序列化和分析请求
    // HttpRequst hr = Deserialize(requst);
    // hr.Print();
     
     //3.使用请求
    // std::string body;
    // std::string response;
    // if (true == Utility::ReadFile(hr.path_, &body))
    // {
    //     // 响应
    //     response = "HTTP/1.0 200 OK" + SEP;                     // 状态行
    //     response += "Content-Length: " + std::to_string(body.size()) + SEP; // 报头行
    //     response += GetSuffix(hr.suffix_);
    //     response += SEP;        // 空行
    //     response += body + SEP; // 有效载荷
    // }
    // else
    // {
    //     Utility::ReadFile(page_404, &body);
    //     response = "HTTP/1.0 404 Not Found" + SEP;                     // 状态行
    //     response += "Content-Length: " + std::to_string(body.size()) + SEP; // 报头行
    //     response += GetSuffix(".html");
    //     response += SEP;        // 空行
    //     response += body + SEP; // 有效载荷
    // }

     // 4. 重定向测试
    // std::string response;
    // response = "HTTP/1.0 301 Moved Permanently" + SEP;      // 状态行
    // response += "Location: https://www.baidu.com/" + SEP;   //报头行
    // response += SEP;                                        // 空行

    // 5. cookie && session实验
    std::string response;
    response = "HTTP/1.0 200 OK" + SEP;
    response += "Set-Cookie: sessionid=1234abcd" + SEP;
    response += SEP;

    return response;
}

void Usage(std::string u)
{
    std::cout << "usage:\n\t" << u << " serverport" << std::endl;
}
int main(int argv, char *argc[])
{
    if (argv != 2)
    {
        Usage(argc[0]);
        exit(USAGE_ERROR);
    }
    uint16_t port = atoi(argc[1]);
    std::unique_ptr<HttpServer> upts(new HttpServer(HandlResponse, port));
    upts->InitServer();
    upts->Start();
    return 0;
}